﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using XboxUserInterface.Forms;
using XboxUserInterface.Keys;
using XboxUserInterface.Properties;
using XboxUserInterface.Settings;
using XboxUserInterface.Variables;
using System.Runtime.InteropServices;


namespace XboxUserInterface
{
    class ControllerHelper
    {
        #region DLLImport

        /// <summary>
        /// Imported from user32.dll.  Places input into the mouse input stream one at a time.
        /// </summary>
        /// <param name="dwFlags">Keycode of peration to insert</param>
        /// <param name="dx">Change in X</param>
        /// <param name="dy">Change in Y</param>
        /// <param name="dwData">If dwFlags indicates scrolling, this is teh amount to scroll (-120 - 120)</param>
        /// <param name="dwExtraInfo">Extra information to add to the data stream</param>
        [DllImport("user32.dll")]
        public static extern void mouse_event(int dwFlags, int dx, int dy, ulong dwData, int dwExtraInfo);

        /// <summary>
        /// Imported from user32.dll.  Place input into the keyboard input stream one key at a time.
        /// </summary>
        /// <param name="bVk">Virtual key code</param>
        /// <param name="bScan">Hardware scane code for key</param>
        /// <param name="dwFlags">Extends the information, typically to specify extended press or a keyup</param>
        /// <param name="dwExtraInfo">Extra information to add to the data stream.</param>
        [DllImport("user32.dll")]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);

        /// <summary>
        /// Imported from user32.dll.  Can add to either the mouse input stream or keyboard input stream multiple strokes at a time.
        /// </summary>
        /// <param name="nInputs">Number of INPUT structures in pInputs</param>
        /// <param name="pInputs">Array of INPUT structures to add to the stream</param>
        /// <param name="cbSize">Size of one INPUT structure.</param>
        /// <returns>Number of events sucessfully inserted into they stream.</returns>
        [DllImport("user32.dll")]
        public static extern int SendInput(int nInputs, INPUT[] pInputs, int cbSize);

        /// <summary>
        /// Gets extra information associated with the input streams.
        /// </summary>
        /// <returns>Extra information for mouse_event and keybd_event</returns>
        [DllImport("user32.dll")]
        public static extern IntPtr GetMessageExtraInfo();

        #endregion

        #region Controller Variables

        private GamePadButtons _buttons;
        private GamePadDPad _dPad;
        private GamePadThumbSticks _tSticks;
        private GamePadTriggers _triggers;

        private GamePadButtons _oButtons;
        private GamePadDPad _oDPad;
        private GamePadThumbSticks _oTSticks;
        private GamePadTriggers _oTriggers;

        /// <summary>
        /// The current status of the buttons in the instance.  Flags the ButtonStateChanged event.
        /// </summary>
        public GamePadButtons Buttons
        {
            get { return _buttons; }
            set
            {
                _oButtons = _buttons;
                _buttons = value;
                ButtonStateChanged(this, new EventArgs());
            }
        }

        /// <summary>
        /// The current status of the D-Pad in the instance.  Flags the DPadStateChanged event.
        /// </summary>
        public GamePadDPad DPad
        {
            get { return _dPad; }
            set
            {
                _oDPad = _dPad;
                _dPad = value;
                DPadStateChanged(this, new EventArgs());
            }
        }

        /// <summary>
        /// The current status of the thumb sticks in the instance.  Flags the ThumbSticksChagned event.
        /// </summary>
        public GamePadThumbSticks ThumbSticks
        {
            get { return _tSticks; }
            set
            {
                _oTSticks = _tSticks;
                _tSticks = value;
                ThumbSticksChanged(this, new EventArgs());
            }
        }

        /// <summary>
        /// The current status of the analog triggers in the instance.  Flags the TriggersChanged event.
        /// </summary>
        public GamePadTriggers Triggers
        {
            get { return _triggers; }
            set
            {
                _oTriggers = _triggers;
                _triggers = value;
                TriggersChanged(this, new EventArgs());
            }
        }

        /// <summary>
        /// The previous status of the buttons in the instance.
        /// </summary>
        public GamePadButtons OldButtons
        {
            get { return _oButtons; }
            set { _oButtons = value; }
        }

        /// <summary>
        /// The previous status of the D-Pad in the instance.
        /// </summary>
        public GamePadDPad OldDPad
        {
            get { return _oDPad; }
            set { _oDPad = value; }
        }

        /// <summary>
        /// The previous status of the thumb sticks in the instance.
        /// </summary>
        public GamePadThumbSticks OldThumbSticks
        {
            get { return _oTSticks; }
            set { _oTSticks = value; }
        }

        /// <summary>
        /// The previous status of the analog triggers in the instance.
        /// </summary>
        public GamePadTriggers OldTriggers
        {
            get { return _oTriggers; }
            set { _oTriggers = value; }
        }

        #endregion

        # region Constructors
        /// <summary>
        /// Initializes an empty instance of ControllerHelper.  Creates the new event handlers corresponding to the TChanged events.
        /// </summary>

        public ControllerHelper()
        {
            ButtonStateChanged += new StateChanged(ControllerHelper_ButtonStateChanged);
            ThumbSticksChanged += new StateChanged(ControllerHelper_ThumbSticksChanged);
            DPadStateChanged += new StateChanged(ControllerHelper_DPadStateChanged);
            TriggersChanged += new StateChanged(ControllerHelper_TriggersChanged);
        }

        #endregion

        #region Event Handlers

        public delegate void StateChanged(object sender, EventArgs e);
        public event StateChanged ButtonStateChanged;
        public event StateChanged ThumbSticksChanged;
        public event StateChanged DPadStateChanged;
        public event StateChanged TriggersChanged;

        /// <summary>
        /// Creates and sends the correct inputs to the keystream for the analog triggers.
        /// </summary>
        /// <param name="sender">Instance of ControllerHelper calling the event</param>
        /// <param name="e">EventArgs to pass to the function</param>
        void ControllerHelper_TriggersChanged(object sender, EventArgs e)
        {
            // Left Trigger
            if (Triggers.Left != OldTriggers.Left && Triggers.Left > 0 && OldTriggers.Left == 0)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftTrigger]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftTrigger], ControllerButtons.leftTrigger)}, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftTrigger]), 0, 0, false);
            
            if(Triggers.Left != OldTriggers.Left && Triggers.Left == 0)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftTrigger]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftTrigger], ControllerButtons.leftTrigger) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftTrigger]), 0, 0, true);

            //Right Trigger
            if (Triggers.Right != OldTriggers.Right && Triggers.Right > 0 && OldTriggers.Right == 0)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightTrigger]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightTrigger], ControllerButtons.rightTrigger) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightTrigger]), 0, 0, false);
            
            if (Triggers.Right != OldTriggers.Right && Triggers.Right == 0)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightTrigger]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightTrigger], ControllerButtons.rightTrigger) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightTrigger]), 0, 0, true);

        }

        /// <summary>
        /// Creates and sends the correct inputs to the keystream for the D-Pad
        /// </summary>
        /// <param name="sender">Instance of ControllerHelper calling the event</param>
        /// <param name="e">EventArgs to pass to the function</param>
        void ControllerHelper_DPadStateChanged(object sender, EventArgs e)
        {
            //D-Pad Up
            if (DPad.Up != OldDPad.Up && DPad.Up == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dUp]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dUp], ControllerButtons.dUp) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dUp]), 0, 0, false);

            if (DPad.Up != OldDPad.Up && DPad.Up == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dUp]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dUp], ControllerButtons.dUp) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dUp]), 0, 0, true);

            //D-Pad Right
            if (DPad.Right != OldDPad.Right && DPad.Right == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dRight]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dRight], ControllerButtons.dRight) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dRight]), 0, 0, false);

            if (DPad.Right != OldDPad.Right && DPad.Right == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dRight]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dRight], ControllerButtons.dRight) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dRight]), 0, 0, true);

            //D-Pad Down
            if (DPad.Down != OldDPad.Down && DPad.Down == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dDown]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dDown], ControllerButtons.dDown) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dDown]), 0, 0, false);

            if (DPad.Down != OldDPad.Down && DPad.Down == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dDown]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dDown], ControllerButtons.dDown) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dDown]), 0, 0, true);

            //D-Pad Left
            if (DPad.Left != OldDPad.Left && DPad.Left == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dLeft]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dLeft], ControllerButtons.dLeft) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dLeft]), 0, 0, false);

            if (DPad.Left != OldDPad.Left && DPad.Left == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dLeft]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dLeft], ControllerButtons.dLeft) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.dLeft]), 0, 0, true);
        }

        /// <summary>
        /// Creates and sends the correct inputs to the keystream for the thumb sticks.
        /// </summary>
        /// <param name="sender">Instance of ControllerHelper calling the event</param>
        /// <param name="e">EventArgs to pass to the function</param>
        void ControllerHelper_ThumbSticksChanged(object sender, EventArgs e)
        {
            MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftAnalog]), ThumbSticks.Left.X, -1 * ThumbSticks.Left.Y, false);
            MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightAnalog]), ThumbSticks.Right.X, -1 * ThumbSticks.Right.Y, false);
        }

        /// <summary>
        /// Creates and sends the correct inputs to the keystream for the buttons.
        /// </summary>
        /// <param name="sender">Instance of ControllerHelper calling the event</param>
        /// <param name="e">EventArgs to pass to the function</param>
        void ControllerHelper_ButtonStateChanged(object sender, EventArgs e)
        {
            //A Button
            if (Buttons.A != OldButtons.A && Buttons.A == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.aButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.aButton], ControllerButtons.aButton) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.aButton]), 0, 0, false);

            if (Buttons.A != OldButtons.A && Buttons.A == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.aButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.aButton], ControllerButtons.aButton) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.aButton]), 0, 0, true);

            //B Button
            if (Buttons.B != OldButtons.B && Buttons.B == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.bButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.bButton], ControllerButtons.bButton) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.bButton]), 0, 0, false);
            
            if (Buttons.B != OldButtons.B && Buttons.B == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.bButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.bButton], ControllerButtons.bButton) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.bButton]), 0, 0, true);

            //X Button
            if (Buttons.X != OldButtons.X && Buttons.X == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.xButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.xButton], ControllerButtons.xButton) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.xButton]), 0, 0, false);

            if (Buttons.X != OldButtons.X && Buttons.X == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.xButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.xButton], ControllerButtons.xButton) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.xButton]), 0, 0, true);

            //Y Button
            if (Buttons.Y != OldButtons.Y && Buttons.Y == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.yButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.yButton], ControllerButtons.yButton) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.yButton]), 0, 0, false);

            if (Buttons.Y != OldButtons.Y && Buttons.Y == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.yButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.yButton], ControllerButtons.yButton) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.yButton]), 0, 0, true);

            //Left Shoulder Button
            if (Buttons.LeftShoulder != OldButtons.LeftShoulder && Buttons.LeftShoulder == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftButton], ControllerButtons.leftButton) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftButton]), 0, 0, false);

            if (Buttons.LeftShoulder != OldButtons.LeftShoulder && Buttons.LeftShoulder == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftButton], ControllerButtons.leftButton) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.leftButton]), 0, 0, true);

            //Right Shoulder Button
            if (Buttons.RightShoulder != OldButtons.RightShoulder && Buttons.RightShoulder == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightButton], ControllerButtons.rightButton) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightButton]), 0, 0, false);
            
            if (Buttons.RightShoulder != OldButtons.RightShoulder && Buttons.RightShoulder == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightButton]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightButton], ControllerButtons.rightButton) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.rightButton]), 0, 0, true);

            //Start Button
            if (Buttons.Start != OldButtons.Start && Buttons.Start == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.startBtn]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.startBtn], ControllerButtons.startBtn) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.startBtn]), 0, 0, false);

            if (Buttons.Start != OldButtons.Start && Buttons.Start == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.startBtn]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.startBtn], ControllerButtons.startBtn) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.startBtn]), 0, 0, true);

            //Back Button
            if (Buttons.Back != OldButtons.Back && Buttons.Back == ButtonState.Pressed)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.backBtn]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.backBtn], ControllerButtons.backBtn) }, false);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.backBtn]), 0, 0, false);

            if (Buttons.Back != OldButtons.Back && Buttons.Back == ButtonState.Released)
                if (!((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.backBtn]).ToString().StartsWith("Mouse"))
                    KeysInput(new List<Key>() { new Key((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.backBtn], ControllerButtons.backBtn) }, true);
                else
                    MouseInput((uint)((KeyboardFunction)Globals.ActiveKeys[ControllerButtons.backBtn]), 0, 0, true);
        }

        #endregion

        #region Send Inputs

        /// <summary>
        /// Creates and sends the input to the keystream for the given keys.
        /// </summary>
        /// <param name="keys">List of keys to send into the stream</param>
        /// <param name="keyUp">Boolean indicating whether the keys should be send with the KEYUP flag</param>
        public static void KeysInput(List<Key> keys, bool keyUp)
        {
            INPUT[] inputs = new INPUT[keys.Count];

            inputs[0] = new INPUT();
            inputs[0].type = Win32Consts.INPUT_KEYBOARD;
            uint dFlag;
            if (keyUp)
                dFlag = Win32Consts.KEYEVENTF_KEYUP;
            else
                dFlag = Win32Consts.KEYEVENTF_EXTENDEDKEY;
            for(int i = 0; i < inputs.Length; i++)
            {
                inputs[i].ki = new KEYBDINPUT() { dwExtraInfo = GetMessageExtraInfo(), wScan = 0, wVk = (ushort)keys[i].KeyCode, dwFlags = dFlag};
            }
            SendInput(inputs.Length, inputs, Marshal.SizeOf(inputs[0]));
        }

        /// <summary>
        /// Creates and sends mouse information to the keystream.
        /// </summary>
        /// <param name="mouseFunction">Virtual keycode of the mouse function to use</param>
        /// <param name="Dx">Change in X direciton</param>
        /// <param name="Dy">Change in Y direction</param>
        /// <param name="keyUp">Boolean indicating whether to send the KEYUP flag with the function</param>
        public static void MouseInput(uint mouseFunction, float Dx, float Dy, bool keyUp)
        {
            INPUT[] inputs = new INPUT[1];
            uint changedFlag = mouseFunction;

            if (keyUp)
            {
                if (mouseFunction == (uint)KeyboardFunction.Mouse_Left)
                    changedFlag = 0x04;
                if (mouseFunction == (uint)KeyboardFunction.Mouse_Right)
                    changedFlag = 0x10;
                if (mouseFunction == (uint)KeyboardFunction.Mouse_Middle)
                    changedFlag = 0x40;
            }

            uint exData = 0;
            if (mouseFunction == 0x800)
                exData = (uint)Math.Round(-10.0 * Convert.ToDouble(Dy));

            int _dx = (int)Math.Round(15 * Convert.ToDecimal(Dx));
            int _dy = (int)Math.Round(15 * Convert.ToDecimal(Dy));

            inputs[0].type = Win32Consts.INPUT_MOUSE;
            inputs[0].mi = new MOUSEINPUT() { dx = _dx, dy = _dy, dwExtraInfo = GetMessageExtraInfo(), dwFlags = changedFlag, mouseData = exData, time = 0 };

            SendInput(inputs.Length, inputs, Marshal.SizeOf(inputs[0]));
        }

        #endregion
    }
}
